home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / gg / ncurses-5.3.lha / ncurses-5.3 / tack / sync.c < prev    next >
C/C++ Source or Header  |  2002-10-24  |  10KB  |  437 lines

  1. /*
  2. ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
  3. ** 
  4. ** This file is part of TACK.
  5. ** 
  6. ** TACK is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2, or (at your option)
  9. ** any later version.
  10. ** 
  11. ** TACK is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** 
  16. ** You should have received a copy of the GNU General Public License
  17. ** along with TACK; see the file COPYING.  If not, write to
  18. ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. ** Boston, MA 02111-1307, USA.
  20. */
  21.  
  22. #include <tack.h>
  23. #include <time.h>
  24.  
  25. MODULE_ID("$Id: sync.c,v 1.3 2001/06/16 17:55:48 tom Exp $")
  26.  
  27. /* terminal-synchronization and performance tests */
  28.  
  29. static void sync_home(struct test_list *, int *, int *);
  30. static void sync_lines(struct test_list *, int *, int *);
  31. static void sync_clear(struct test_list *, int *, int *);
  32. static void sync_summary(struct test_list *, int *, int *);
  33.  
  34. struct test_list sync_test_list[] = {
  35.     {MENU_NEXT, 0, 0, 0, "b) baud rate test", sync_home, 0},
  36.     {MENU_NEXT, 0, 0, 0, "l) scroll performance", sync_lines, 0},
  37.     {MENU_NEXT, 0, 0, 0, "c) clear screen performance", sync_clear, 0},
  38.     {MENU_NEXT, 0, 0, 0, "p) summary of results", sync_summary, 0},
  39.     {0, 0, 0, 0, txt_longer_test_time, longer_test_time, 0},
  40.     {0, 0, 0, 0, txt_shorter_test_time, shorter_test_time, 0},
  41.     {MENU_LAST, 0, 0, 0, 0, 0, 0}
  42. };
  43.  
  44. struct test_menu sync_menu = {
  45.     0, 'n', 0,
  46.     "Performance tests", "perf", "n) run standard tests",
  47.     sync_test, sync_test_list, 0, 0, 0
  48. };
  49.  
  50. int tty_can_sync;        /* TRUE if tty_sync_error() returned FALSE */
  51. int tty_newline_rate;        /* The number of newlines per second */
  52. int tty_clear_rate;        /* The number of clear-screens per second */
  53. int tty_cps;            /* The number of characters per second */
  54.  
  55. #define TTY_ACK_SIZE 64
  56.  
  57. int ACK_terminator;        /* terminating ACK character */
  58. int ACK_length;            /* length of ACK string */
  59. const char *tty_ENQ;        /* enquire string */
  60. char tty_ACK[TTY_ACK_SIZE];    /* ACK response, set by tty_sync_error() */
  61.  
  62. /*****************************************************************************
  63.  *
  64.  * Terminal synchronization.
  65.  *
  66.  *    These functions handle the messy business of enq-ack handshaking
  67.  *    for timing purposes.
  68.  *
  69.  *****************************************************************************/
  70.  
  71. int
  72. tty_sync_error(void)
  73. {
  74.     int ch, trouble, ack;
  75.  
  76.     trouble = FALSE;
  77.     for (;;) {
  78.         tt_putp(tty_ENQ);    /* send ENQ */
  79.         ch = getnext(STRIP_PARITY);
  80.         event_start(TIME_SYNC);    /* start the timer */
  81.  
  82.         /*
  83.            The timer doesn't start until we get the first character.
  84.            After that I expect to get the remaining characters of
  85.            the acknowledge string in a short period of time.  If
  86.            that is not true then these characters are coming from
  87.            the user and we need to send the ENQ sequence out again.
  88.         */
  89.         for (ack = 0; ; ) {
  90.             if (ack < TTY_ACK_SIZE - 2) {
  91.                 tty_ACK[ack] = ch;
  92.                 tty_ACK[ack + 1] = '\0';
  93.             }
  94.             if (ch == ACK_terminator) {
  95.                 return trouble;
  96.             }
  97.             if (++ack >= ACK_length) {
  98.                 return trouble;
  99.             }
  100.             ch = getnext(STRIP_PARITY);
  101.             if (event_time(TIME_SYNC) > 400000) {
  102.                 break;
  103.             }
  104.         }
  105.  
  106.         set_attr(0);    /* just in case */
  107.         put_crlf();
  108.         if (trouble) {
  109.             /* The terminal won't sync.  Life is not good. */
  110.             return TRUE;
  111.         }
  112.         put_str(" -- sync -- ");
  113.         trouble = TRUE;
  114.     }
  115. }
  116.  
  117. /*
  118. **    flush_input()
  119. **
  120. **    Throw away any output.
  121. */
  122. void 
  123. flush_input(void)
  124. {
  125.     if (tty_can_sync == SYNC_TESTED && ACK_terminator >= 0) {
  126.         (void) tty_sync_error();
  127.     } else {
  128.         spin_flush();
  129.     }
  130. }
  131.  
  132. /*
  133. **    probe_enq_ok()
  134. **
  135. **    does the terminal do enq/ack handshaking?
  136. */
  137. static void 
  138. probe_enq_ok(void)
  139. {
  140.     int tc, len, ulen;
  141.  
  142.     put_str("Testing ENQ/ACK, standby...");
  143.     fflush(stdout);
  144.     can_test("u8 u9", FLAG_TESTED);
  145.  
  146. #ifdef user9
  147.     tty_ENQ = user9 ? user9 : "\005";
  148. #else
  149.     tty_ENQ = "\005";
  150. #endif
  151.     tc_putp(tty_ENQ);
  152.     event_start(TIME_SYNC);    /* start the timer */
  153.     read_key(tty_ACK, TTY_ACK_SIZE - 1);
  154.  
  155.     if (event_time(TIME_SYNC) > 400000 || tty_ACK[0] == '\0') {
  156.         /* These characters came from the user.  Sigh. */
  157.         tty_can_sync = SYNC_FAILED;
  158.         ptext("\nThis program expects the ENQ sequence to be");
  159.         ptext(" answered with the ACK character.  This will help");
  160.         ptext(" the program reestablish synchronization when");
  161.         ptextln(" the terminal is overrun with data.");
  162.         ptext("\nENQ sequence from (u9): ");
  163.         putln(expand(tty_ENQ));
  164.         ptext("ACK received: ");
  165.         putln(expand(tty_ACK));
  166. #ifdef user8
  167.         len = user8 ? strlen(user8) : 0;
  168. #else
  169.         len = 0;
  170. #endif
  171.         sprintf(temp, "Length of ACK %d.  Expected length of ACK %d.",
  172.             (int) strlen(tty_ACK), len);
  173.         ptextln(temp);
  174. #ifdef user8
  175.         if (len) {
  176.             temp[0] = user8[len - 1];
  177.             temp[1] = '\0';
  178.             ptext("Terminating character found in (u8): ");
  179.             putln(expand(temp));
  180.         }
  181. #endif
  182.         return;
  183.     }
  184.  
  185.     tty_can_sync = SYNC_TESTED;
  186.     if ((len = strlen(tty_ACK)) == 1) {
  187.         /* single character acknowledge string */
  188.         ACK_terminator = tty_ACK[0];
  189.         ACK_length = 4096;
  190.         return;
  191.     }
  192.     tc = tty_ACK[len - 1];
  193. #ifdef user8
  194.     if (user8) {
  195.         ulen = strlen(user8);
  196.         if (tc == user8[ulen - 1]) {
  197.             /* ANSI style acknowledge string */
  198.             ACK_terminator = tc;
  199.             ACK_length = 4096;
  200.             return;
  201.         }
  202.     }
  203. #endif
  204.     /* fixed length acknowledge string */
  205.     ACK_length = len;
  206.     ACK_terminator = -2;
  207. }
  208.  
  209. /*
  210. **    verify_time()
  211. **
  212. **    verify that the time tests are ready to run.
  213. **    If the baud rate is not set then compute it.
  214. */
  215. void
  216. verify_time(void)
  217. {
  218.     int status, ch;
  219.  
  220.     if (tty_can_sync == SYNC_FAILED) {
  221.         return;
  222.     }
  223.     probe_enq_ok();
  224.     put_crlf();
  225.     if (tty_can_sync == SYNC_TESTED) {
  226.         put_crlf();
  227.         if (ACK_terminator >= 0) {
  228.             ptext("ACK terminating character: ");
  229.             temp[0] = ACK_terminator;
  230.             temp[1] = '\0';
  231.             ptextln(expand(temp));
  232.         } else {
  233.             sprintf(temp, "Fixed length ACK, %d characters",
  234.                 ACK_length);
  235.             ptextln(temp);
  236.         }
  237.     }
  238.     if (tty_baud_rate == 0) {
  239.         sync_home(&sync_test_list[0], &status, &ch);
  240.     }
  241. }
  242.  
  243. /*****************************************************************************
  244.  *
  245.  * Terminal performance tests
  246.  *
  247.  *    Find out how fast the terminal can:
  248.  *      1) accept characters
  249.  *      2) scroll the screen
  250.  *      3) clear the screen
  251.  *
  252.  *****************************************************************************/
  253.  
  254. /*
  255. **    sync_home(test_list, status, ch)
  256. **
  257. **    Baudrate test
  258. */
  259. void
  260. sync_home(
  261.     struct test_list *t,
  262.     int *state,
  263.     int *ch)
  264. {
  265.     int j, k;
  266.     unsigned long rate;
  267.  
  268.     if (!cursor_home && !cursor_address && !row_address) {
  269.         ptext("Terminal can not home cursor.  ");
  270.         generic_done_message(t, state, ch);
  271.         return;
  272.     }
  273.     if (skip_pad_test(t, state, ch,
  274.         "(home) Start baudrate search")) {
  275.         return;
  276.     }
  277.     pad_test_startup(1);
  278.     do {
  279.         go_home();
  280.         for (j = 1; j < lines; j++) {
  281.             for (k = 0; k < columns; k++) {
  282.                 if (k & 0xF) {
  283.                     put_this(letter);
  284.                 } else {
  285.                     put_this('.');
  286.                 }
  287.             }
  288.             SLOW_TERMINAL_EXIT;
  289.         }
  290.         NEXT_LETTER;
  291.     } while(still_testing());
  292.     pad_test_shutdown(t, auto_right_margin == 0);
  293.     /* note:  tty_frame_size is the real framesize times two.
  294.        This takes care of half bits. */
  295.     rate = (tx_cps * tty_frame_size) >> 1;
  296.     if (rate > tty_baud_rate) {
  297.         tty_baud_rate = rate;
  298.     }
  299.     if (tx_cps > tty_cps) {
  300.         tty_cps = tx_cps;
  301.     }
  302.     sprintf(temp, "%d characters per second.  Baudrate %d  ", tx_cps, j);
  303.     ptext(temp);
  304.     generic_done_message(t, state, ch);
  305. }
  306.  
  307. /*
  308. **    sync_lines(test_list, status, ch)
  309. **
  310. **    How many newlines/second?
  311. */
  312. static void
  313. sync_lines(
  314.     struct test_list *t,
  315.     int *state,
  316.     int *ch)
  317. {
  318.     int j;
  319.  
  320.     if (skip_pad_test(t, state, ch,
  321.         "(nel) Start scroll performance test")) {
  322.         return;
  323.     }
  324.     pad_test_startup(0);
  325.     repeats = 100;
  326.     do {
  327.         sprintf(temp, "%d", test_complete);
  328.         put_str(temp);
  329.         put_newlines(repeats);
  330.     } while(still_testing());
  331.     pad_test_shutdown(t, 0);
  332.     j = sliding_scale(tx_count[0], 1000000, usec_run_time);
  333.     if (j > tty_newline_rate) {
  334.         tty_newline_rate = j;
  335.     }
  336.     sprintf(temp, "%d linefeeds per second.  ", j);
  337.     ptext(temp);
  338.     generic_done_message(t, state, ch);
  339. }
  340.  
  341. /*
  342. **    sync_clear(test_list, status, ch)
  343. **
  344. **    How many clear-screens/second?
  345. */
  346. static void
  347. sync_clear(
  348.     struct test_list *t,
  349.     int *state,
  350.     int *ch)
  351. {
  352.     int j;
  353.  
  354.     if (!clear_screen) {
  355.         ptext("Terminal can not clear-screen.  ");
  356.         generic_done_message(t, state, ch);
  357.         return;
  358.     }
  359.     if (skip_pad_test(t, state, ch,
  360.         "(clear) Start clear-screen performance test")) {
  361.         return;
  362.     }
  363.     pad_test_startup(0);
  364.     repeats = 20;
  365.     do {
  366.         sprintf(temp, "%d", test_complete);
  367.         put_str(temp);
  368.         for (j = 0; j < repeats; j++) {
  369.             put_clear();
  370.         }
  371.     } while(still_testing());
  372.     pad_test_shutdown(t, 0);
  373.     j = sliding_scale(tx_count[0], 1000000, usec_run_time);
  374.     if (j > tty_clear_rate) {
  375.         tty_clear_rate = j;
  376.     }
  377.     sprintf(temp, "%d clear-screens per second.  ", j);
  378.     ptext(temp);
  379.     generic_done_message(t, state, ch);
  380. }
  381.  
  382. /*
  383. **    sync_summary(test_list, status, ch)
  384. **
  385. **    Print out the test results.
  386. */
  387. static void
  388. sync_summary(
  389.     struct test_list *t,
  390.     int *state,
  391.     int *ch)
  392. {
  393.     char size[32];
  394.  
  395.     put_crlf();
  396.     ptextln("Terminal  size    characters/sec linefeeds/sec  clears/sec");
  397.     sprintf(size, "%dx%d", columns, lines);
  398.     sprintf(temp, "%-10s%-11s%11d   %11d %11d", tty_basename, size,
  399.         tty_cps, tty_newline_rate, tty_clear_rate);
  400.     ptextln(temp);
  401.     generic_done_message(t, state, ch);
  402. }
  403.  
  404. /*
  405. **    sync_test(menu)
  406. **
  407. **    Run at the beginning of the pad tests and function key tests
  408. */
  409. void
  410. sync_test(
  411.     struct test_menu *menu)
  412. {
  413.     control_init();
  414.     if (tty_can_sync == SYNC_NOT_TESTED) {
  415.         verify_time();
  416.     }
  417.     if (menu->menu_title) {
  418.         put_crlf();
  419.         ptextln(menu->menu_title);
  420.     }
  421. }
  422.  
  423. /*
  424. **    sync_handshake(test_list, status, ch)
  425. **
  426. **    Test or retest the ENQ/ACK handshake
  427. */
  428. void
  429. sync_handshake(
  430.     struct test_list *t GCC_UNUSED,
  431.     int *state GCC_UNUSED,
  432.     int *ch GCC_UNUSED)
  433. {
  434.     tty_can_sync = SYNC_NOT_TESTED;
  435.     verify_time();
  436. }
  437.